
#include "cache.h"
#include <string.h>
#include <stdlib.h>
#include "nemu.h"

void init_cache() {
    int i, j;
    for ( i = 0; i < CACHE_SET_NUM; i++) {
        for ( j = 0; j < CACHE_WAY_NUM; j++) {
            cache[i][j].valid_bit = 0;
            cache[i][j].tag = 0;
            int k;
            for ( k = 0; k < 64; k++) {
                cache[i][j].data[k] = 0;
            }
        }
    }
}

uint32_t cache_read( uint32_t addr, mem_cacheline *data) {
    uint32_t set_index = (addr >> 6) & 0x7f;
    uint32_t tag = (addr >> 13) & 0x1ffff;
    // Log("cache read in tag %x, set_index %x", tag, set_index);
    int i;
    for (i = 0; i < CACHE_WAY_NUM; i++) {
        if (cache[set_index][i].valid_bit == 1 && cache[set_index][i].tag == tag) {
            //直接读取一行的数据
            // Log("cache hit in tag %x, set_index %x", tag, set_index);
            memcpy(data->data, cache[set_index][i].data, 64);
            return 0;
        }
    }
    return 1;
}


void cache_write(uint32_t addr, mem_cacheline *data) {
    uint32_t set_index = (addr >> 6) & 0x7f;
    uint32_t tag = (addr >> 13) & 0x1ffff;
    // Log("cache write in tag %x, set_index %x, data %x", tag, set_index, *(uint32_t *)data);
    int i;

    // 查找空闲的cache line
    for (i = 0; i < CACHE_WAY_NUM; i++) {
        if (cache[set_index][i].valid_bit == 0) {
            cache[set_index][i].valid_bit = 1;
            cache[set_index][i].tag = tag;

            int j;
            for (j = 0; j < 64; j++) {
                // Log("data->data[%d] = %x", j, data->data[j]);
                cache[set_index][i].data[j] = data->data[j];
            }
            // memcpy(cache[set_index][i].data, data->data, 64);
            // Log("cache write in tag %x, set_index %x, data %x", tag, set_index, *(uint32_t *)data);
            // 打印cache的内容
            // for (i = 0; i < CACHE_WAY_NUM; i++) {
            //     Log("cache[%d][%d].valid_bit = %d, cache[%d][%d].tag = %x", set_index, i, cache[set_index][i].valid_bit, set_index, i, cache[set_index][i].tag);
            // }
            // for (j = 0; j < 64; j++) {
            //     Log("cache[%d][%d].data[%d] = %x", set_index, i, j, cache[set_index][i].data[j]);
            // }
            return;
        }
    }
    // 如果没有空闲的cache line，随机替换一个
    i = rand() % CACHE_WAY_NUM;
    cache[set_index][i].tag = tag;
    for (i = 0; i < 64; i++) {
        cache[set_index][i].data[i] = data->data[i];
    }

    // Log("cache write %x", *(uint32_t *)data);
}